package com.manage.platform.excel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.manage.platform.exception.CommonException;
import com.manage.platform.properties.ExcelProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * YWD
 * 2025/11/18
 */
@AllArgsConstructor
@Slf4j
@Service
public class UserExcelServiceImpl {

    private final ExcelProperties excelProperties;

    // 日期时间格式化器
    private static final DateTimeFormatter DATE_TIME_FORMATTER =
            DateTimeFormatter.ofPattern("yyyyMMdd");

    /**
     * 生成 Excel 报表（使用字节数组方式）
     * 将文件保存到指定目录，并返回文件路径或URL
     */
    public String createReport() {
        FileOutputStream fileOutputStream = null;
        try {
            // 准备数据
            UserExcel userExcel = new UserExcel();
            userExcel.setId(1L);
            userExcel.setRoleName("普通用户");
            userExcel.setUserName("51000010");
            userExcel.setRealName("张三");
            userExcel.setGender(0);
            List<UserExcel> list = Collections.singletonList(userExcel);
            // 确保存储目录存在
            ensureReportDirectoryExists();
            // 生成唯一文件名
            String fileName = generateFileName();
            String fullFilePath = excelProperties.getPath() + File.separator + fileName;
            // 生成 Excel 文件
            EasyExcel.write(fullFilePath, UserExcel.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自动列宽
                    .sheet("出入库报表")
                    .doWrite(list);
            log.info("Excel文件生成成功！路径: {}", fullFilePath);
            // 返回文件路径或URL
            if (excelProperties.getWeb()) {
                // 返回Web可访问的URL
                return excelProperties.getUrl() + "/" + fileName;
            } else {
                // 返回文件系统绝对路径
                return new File(fullFilePath).getAbsolutePath();
            }
        } catch (Exception e) {
            log.error("生成报表失败", e);
            throw new CommonException("生成报表失败: " + e.getMessage());
        } finally {
            // 确保资源关闭
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    log.warn("关闭文件输出流失败", e);
                }
            }
        }
    }

    /**
     * 生成带时间戳的唯一文件名
     */
    private String generateFileName() {
        //String timestamp = LocalDateTime.now().format(DATE_TIME_FORMATTER);
        //String uuid = UUID.randomUUID().toString().substring(0, 4);
        return "user" + ".xlsx";
    }

    /**
     * 确保报表存储目录存在
     */
    private void ensureReportDirectoryExists() throws IOException {
        Path path = Paths.get(excelProperties.getPath());
        if (!Files.exists(path)) {
            Files.createDirectories(path);
            log.info("创建报表存储目录: {}", path.toAbsolutePath());
        }
    }

    /**
     * 生成Excel报表并返回字节数组（适用于web下载）
     */
    public byte[] createReportAsBytes() {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            // 准备数据
            UserExcel userExcel = new UserExcel();
            userExcel.setId(1L);
            userExcel.setRoleName("普通用户");
            userExcel.setUserName("51000010");
            userExcel.setRealName("张三");
            userExcel.setProfessionalName("教授");
            userExcel.setPositionName("教授（正高级）");
            userExcel.setGender(0);
            List<UserExcel> list = Collections.singletonList(userExcel);

            // 生成 Excel 到字节数组
            EasyExcel.write(outputStream, UserExcel.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet("用户报表")
                    .doWrite(list);
            return outputStream.toByteArray();
        } catch (Exception e) {
            log.error("生成报表失败", e);
            throw new CommonException("生成报表失败: " + e.getMessage());
        }
    }

    /**
     * 生成自定义数据的Excel报表
     */
    public String createReport(List<UserExcel> data, String sheetName) {
        try {
            // 确保存储目录存在
            ensureReportDirectoryExists();
            // 生成唯一文件名
            String fileName = generateFileName();
            String fullFilePath = excelProperties.getPath() + File.separator + fileName;
            // 使用自定义sheet名称，默认为"报表"
            String finalSheetName = StringUtils.hasText(sheetName) ? sheetName : "报表";
            // 生成 Excel 文件
            EasyExcel.write(fullFilePath, UserExcel.class)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                    .sheet(finalSheetName)
                    .doWrite(data);
            // 返回文件路径或URL
            if (excelProperties.getWeb()) {
                return excelProperties.getUrl() + "/" + fileName;
            } else {
                return new File(fullFilePath).getAbsolutePath();
            }
        } catch (Exception e) {
            log.error("生成报表失败", e);
            throw new CommonException("生成报表失败: " + e.getMessage());
        }
    }

    /**
     * 获取所有已生成的报表文件列表
     */
    public List<String> listReportFiles() {
        try {
            ensureReportDirectoryExists();
            File reportDir = new File(excelProperties.getPath());
            if (reportDir.exists() && reportDir.isDirectory()) {
                File[] files = reportDir.listFiles((dir, name) ->
                        name.toLowerCase().endsWith(".xlsx"));
                if (files != null) {
                    return Arrays.stream(files)
                            .map(File::getName)
                            .sorted(Comparator.reverseOrder()) // 按文件名倒序（最新在前）
                            .collect(Collectors.toList());
                }
            }
            return Collections.emptyList();
        } catch (Exception e) {
            log.error("获取报表文件列表失败", e);
            return Collections.emptyList();
        }
    }

    /**
     * 删除指定的报表文件
     */
    public boolean deleteReport(String fileName) {
        try {
            // 安全检查：防止路径遍历攻击
            if (fileName != null && fileName.contains("..")) {
                log.warn("尝试删除非法文件: {}", fileName);
                return false;
            }
            File file = new File(excelProperties.getPath() + File.separator + fileName);
            if (file.exists() && file.isFile()) {
                boolean deleted = file.delete();
                if (deleted) {
                    log.info("删除报表文件成功: {}", fileName);
                } else {
                    log.warn("删除报表文件失败: {}", fileName);
                }
                return deleted;
            }
            log.warn("报表文件不存在: {}", fileName);
            return false;

        } catch (Exception e) {
            log.error("删除报表文件失败: {}", fileName, e);
            return false;
        }
    }

    /**
     * 清理过期的报表文件（保留最近N天的文件）
     */
    public int cleanupOldReports(int daysToKeep) {
        try {
            ensureReportDirectoryExists();
            File reportDir = new File(excelProperties.getPath());
            if (reportDir.exists() && reportDir.isDirectory()) {
                File[] files = reportDir.listFiles((dir, name) ->
                        name.toLowerCase().endsWith(".xlsx"));
                if (files != null) {
                    long cutoffTime = System.currentTimeMillis() - (daysToKeep * 24L * 60 * 60 * 1000);
                    int deletedCount = 0;

                    for (File file : files) {
                        if (file.lastModified() < cutoffTime) {
                            if (file.delete()) {
                                deletedCount++;
                                log.debug("删除过期报表文件: {}", file.getName());
                            } else {
                                log.warn("删除过期报表文件失败: {}", file.getName());
                            }
                        }
                    }
                    log.info("清理过期报表文件完成，共删除 {} 个文件", deletedCount);
                    return deletedCount;
                }
            }
            return 0;
        } catch (Exception e) {
            log.error("清理过期报表文件失败", e);
            return 0;
        }
    }

}
